library(ggplot2)
library(dplyr)
library(corrplot)
library(readxl)
library(lmtest) 
library(forecast)
library(DIMORA)
library(fpp2)
library(tidyr)
library(lubridate)
number_of_employees <- read_excel("~/Desktop/Unipd/GitHub/Business-Project/Business Project/number-of-employees.xlsx")
quarterly_net_income <- read_excel("~/Desktop/Unipd/GitHub/Business-Project/Business Project/quarterly-net-income.xlsx")
research_development_spending <- read_excel("~/Desktop/Unipd/GitHub/Business-Project/Business Project/research-development-spending.xlsx")
revenue_by_quarter <- read_excel("~/Desktop/Unipd/GitHub/Business-Project/Business Project/revenue-by-quarter.xlsx")
revenue_by_segment <- read_excel("~/Desktop/Unipd/GitHub/Business-Project/Business Project/revenue-by-segment.xlsx")
# Rimuovere le prime 4 righe e l'ultima riga
revenue_by_quarter <- revenue_by_quarter %>%
  slice(5:(n() - 1))

research_development_spending <- research_development_spending %>%
  slice(4:n())

number_of_employees <- number_of_employees %>%
  slice(2:n())
# Normalizzare i dati
normalize <- function(x) {
  return((x - mean(x)) / sd(x))
}

# Ripetere i valori annuali per ciascuno dei quattro trimestri
repeat_annual_data <- function(annual_data) {
  return(rep(annual_data, each = 4))
}

employees_repeated <- repeat_annual_data(number_of_employees$employees)
spending_repeated <- repeat_annual_data(research_development_spending$billion)

# Normalizzare i dati annuali ripetuti
n_employees <- normalize(employees_repeated)
n_spending <- normalize(spending_repeated)

n_revenue <- normalize(revenue)
n_net_income <- normalize(net_income)

# Creare un dataframe combinato
combined_data <- data.frame(
  Quarter = tt,
  Revenue = n_revenue,
  Net_Income = n_net_income,
  Employees = n_employees,
  Spending = n_spending
)

# Trasformare il dataframe in formato lungo
combined_data_long <- combined_data %>%
  pivot_longer(cols = c("Revenue", "Net_Income", "Employees", "Spending"), names_to = "Metric", values_to = "Value")

# Creare il grafico
ggplot(data = combined_data_long, aes(x = Quarter, y = Value, color = Metric)) +
  geom_line() +
  labs(x = "Quarter", y = "Value", title = "Quarterly Revenue and Net Income") +
  theme_minimal()

# Sostituisci i valori NA con zero
revenue_by_segment[is.na(revenue_by_segment)] <- 0

# Trasforma i dati in formato lungo per ggplot2
df_long <- revenue_by_segment %>%
  pivot_longer(cols = -year, names_to = "category", values_to = "value")

# Seleziona una palette di colori con abbastanza variazioni
palette_colors <- c("#66c2a5", "#fc8d62", "#8da0cb", "#e78ac3", "#a6d854", 
                    "#ffd92f", "#e5c494", "#b3b3b3", "#1b9e77", "#d95f02", 
                    "#7570b3", "#e7298a", "#66a61e", "#e6ab02", "#a6761d", "#666666")

# Crea il grafico
ggplot(df_long, aes(x = factor(year), y = value, fill = category)) +
  geom_bar(stat = "identity", position = "stack") +  # Usa "stack" per impilare le barre
  labs(x = "Year", y = "Value", title = "Annual Data by Category") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1), 
        legend.position = "right",  # Sposta la legenda a destra
        legend.text = element_text(size = 7),
        legend.title = element_text(size = 8)) +
  scale_fill_manual(values = palette_colors) +
  guides(fill = guide_legend(ncol = 1, byrow = TRUE))  # Migliora la leggibilità della legenda

# Assicurati che tutte le colonne utilizzate per la correlazione siano numeriche
# Supponiamo che i dati siano nelle colonne 2 delle rispettive tabelle (adatta l'indice di colonna se necessario)
data_combined <- data.frame(
  revenue = revenue_by_quarter$billion,
  net_income = quarterly_net_income$income,
  employees = employees_repeated,
  rnd_spending = spending_repeated
)

# Calcolo della matrice di correlazione
correlation_matrix <- cor(data_combined, use = "complete.obs")

# Visualizzazione della matrice di correlazione
print(correlation_matrix)
               revenue net_income employees rnd_spending
revenue      1.0000000  0.4142986 0.8253796    0.8352008
net_income   0.4142986  1.0000000 0.1724034    0.1767102
employees    0.8253796  0.1724034 1.0000000    0.9728936
rnd_spending 0.8352008  0.1767102 0.9728936    1.0000000
# Se desideri una visualizzazione grafica
library(corrplot)
corrplot(correlation_matrix, method = "circle")


# Creazione delle serie temporali
revenue.ts <- ts(revenue_by_quarter$billion, frequency = 4)
net_income.ts <- ts(quarterly_net_income$income, frequency = 4)
employees_repeated <- ts(employees_repeated, frequency = 4)
spending_repeated <- ts(spending_repeated, frequency = 4)

# Differenziazione delle serie temporali
diff_revenue <- diff(revenue.ts)
diff_net_income <- diff(net_income.ts)
diff_employees <- diff(employees_repeated)
diff_spending <- diff(spending_repeated)

# Creazione del dataframe con le serie differenziate
data_combined_diff <- data.frame(
  diff_revenue = as.numeric(diff_revenue),
  diff_net_income = as.numeric(diff_net_income),
  diff_employees = as.numeric(diff_employees),
  diff_spending = as.numeric(diff_spending)
)

# Calcolo della matrice di correlazione
correlation_matrix_diff <- cor(data_combined_diff, use = "complete.obs")

# Visualizzazione della matrice di correlazione
print(correlation_matrix_diff)
                diff_revenue diff_net_income diff_employees diff_spending
diff_revenue       1.0000000       0.4969756     -0.4245670    -0.4508853
diff_net_income    0.4969756       1.0000000     -0.2592996    -0.2821900
diff_employees    -0.4245670      -0.2592996      1.0000000     0.7179994
diff_spending     -0.4508853      -0.2821900      0.7179994     1.0000000
# Visualizzazione grafica della matrice di correlazione
corrplot(correlation_matrix_diff, method = "circle")

tt <- 1:NROW(revenue_by_quarter)
revenue <- revenue_by_quarter$billion
net_income <- quarterly_net_income$income
revenue_by_quarter$quarter <- as.yearqtr(revenue_by_quarter$quarter, format = "Q%q '%y")

tsdisplay(revenue)


# Calcolo della media mobile (esempio con finestra di 12 mesi per dati mensili)
moving_average <- ma(revenue, order = 12)

ggplot(data = revenue_by_quarter, aes(x = tt)) +
  geom_line(aes(y = billion)) +
  geom_line(aes(y = moving_average), color = "red") +
  labs(x = "Quarter", y = "Billion", title = "Quarter vs. Billion")

NA
NA
NA
# Aggiungi colonne per anno e trimestre
revenue_by_quarter <- revenue_by_quarter %>%
  mutate(
    year = as.integer(format(quarter, "%Y")),
    quarter_num = as.integer(format(quarter, "%q"))
  )

# Crea un grafico stagionale
ggplot(revenue_by_quarter, aes(x = quarter_num, y = billion, group = year, color = factor(year))) +
  geom_line() +
  scale_x_continuous(breaks = 1:4, labels = c("Q1", "Q2", "Q3", "Q4")) +
  labs(x = "Quarter", y = "Revenue (Billion)", title = "Seasonal Plot: Revenue by Quarter", color = "Year") +
  theme_minimal() +
  theme(legend.position = "right")

#Dato che i dati mostrano una tendenza, potrebbe essere necessario differenziare i dati per renderli stazionari prima di applicare un modello ARIMA.

# Differenziazione dei dati
diff_revenue <- diff(revenue)

# Visualizzazione dei dati differenziati
plot(diff_revenue, type = "l", main = "Differenced Revenue")


# Test di stazionarietà (ad esempio, test di Dickey-Fuller aumentato)
library(tseries)
adf.test(diff_revenue)

    Augmented Dickey-Fuller Test

data:  diff_revenue
Dickey-Fuller = -1.6424, Lag order = 3, p-value = 0.7197
alternative hypothesis: stationary
# Creare la serie temporale
revenue_ts <- ts(revenue_by_quarter$billion, start=c(2007, 1), frequency=4)

# Decomporre la serie temporale
decomposed_revenue <- stl(revenue_ts, s.window="periodic")

# Visualizzare la decomposizione
autoplot(decomposed_revenue) +
  labs(title = "Decomposition of Quarterly Revenue", x = "Time")


# Estrarre la componente stagionale
seasonal_component <- decomposed_revenue$time.series[, "seasonal"]

# Creare il grafico della stagionalità
ggplot(data = data.frame(Quarter = time(revenue_ts), Seasonal = seasonal_component), 
       aes(x = Quarter, y = Seasonal)) +
  geom_line(color = "blue") +
  labs(x = "Quarter", y = "Seasonal Component", title = "Seasonal Component of Quarterly Revenue") +
  theme_minimal()

library(forecast)
library(tseries)

# Creare la serie temporale
revenue_ts <- ts(revenue_by_quarter$billion, start=c(2007, 1), frequency=4)

# Differenziare i dati per renderli stazionari
diff_revenue <- diff(revenue_ts, differences=1)

# Calcolare e tracciare l'ACF e la PACF della serie differenziata
acf(diff_revenue, main="ACF of Differenced Revenue")

pacf(diff_revenue, main="PACF of Differenced Revenue")


# Utilizzare auto.arima per trovare il miglior modello ARIMA
best_arima_model <- auto.arima(revenue_ts)
summary(best_arima_model)
Series: revenue_ts 
ARIMA(2,0,2)(0,1,0)[4] with drift 

Coefficients:
         ar1      ar2      ma1     ma2   drift
      1.2299  -0.5551  -0.4580  0.8865  0.1168
s.e.  0.1432   0.1442   0.1082  0.0810  0.0466

sigma^2 = 0.1217:  log likelihood = -21.63
AIC=55.26   AICc=56.84   BIC=67.83

Training set error measures:
                       ME      RMSE      MAE        MPE     MAPE      MASE      ACF1
Training set 0.0003898554 0.3233628 0.226715 0.02214281 2.493414 0.3883215 0.0473361
residuals_arima <- residuals(best_arima_model)

# Visualizzare i residui del modello
checkresiduals(best_arima_model)

    Ljung-Box test

data:  Residuals from ARIMA(2,0,2)(0,1,0)[4] with drift
Q* = 5.5134, df = 4, p-value = 0.2386

Model df: 4.   Total lags used: 8

# Prevedere i prossimi 8 trimestri
forecast_horizon <- 12
forecast_revenue <- forecast(best_arima_model, h = forecast_horizon)

# Visualizzare le previsioni
autoplot(forecast_revenue) +
  labs(title = "Revenue Forecast with ARIMA", x = "Date", y = "Revenue (Billion)") +
  autolayer(fitted(best_arima_model), series = "Fitted", PI = FALSE)
Warning: Ignoring unknown parameters: `PI`

air.model <- Arima(window(revenue_ts,end=2022),order=c(2,0,2),
                   seasonal=list(order=c(0,1,0),period=4),lambda=0)
plot(forecast(air.model,h=12))
lines(revenue_ts)

# Funzione per visualizzare il modello
plot_model <- function(model, data) {
  plot(data, ylab="Billion", xlab="Time")
  lines(fitted(model), col=2)
}

plot_model_forecast <- function(model, data, forecast_horizon) {
  forecasted_values <- forecast(model, h = forecast_horizon)
  plot(forecasted_values, ylab = "Billion", xlab = "Time")
  lines(fitted(model), col = 2)
}

# Modello con trend e stagionalità
fit_lm <- tslm(revenue.ts ~ trend + season)
summary(fit_lm)

Call:
tslm(formula = revenue.ts ~ trend + season)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.6546 -0.6215 -0.1046  0.8287  1.6255 

Coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept) 5.712785   0.300266  19.026  < 2e-16 ***
trend       0.079991   0.006233  12.834  < 2e-16 ***
season2     0.563759   0.325112   1.734   0.0881 .  
season3     0.584393   0.325291   1.797   0.0775 .  
season4     2.161903   0.325590   6.640  1.1e-08 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.9194 on 59 degrees of freedom
Multiple R-squared:  0.7917,    Adjusted R-squared:  0.7776 
F-statistic: 56.07 on 4 and 59 DF,  p-value: < 2.2e-16
# Verifica dei residui
checkresiduals(fit_lm)

    Breusch-Godfrey test for serial correlation of order up to 8

data:  Residuals from Linear regression model
LM test = 51.71, df = 8, p-value = 1.915e-08

# Visualizzazione del modello
plot_model(fit_lm, revenue.ts)


plot_model_forecast(fit_lm, revenue.ts, forecast_horizon = 8)

# Modello Holt-Winters
fit_hw <- hw(revenue.ts, seasonal = "additive")
summary(fit_hw)

Forecast method: Holt-Winters' additive method

Model Information:
Holt-Winters' additive method 

Call:
 hw(y = revenue.ts, seasonal = "additive") 

  Smoothing parameters:
    alpha = 0.6867 
    beta  = 0.3438 
    gamma = 0.3133 

  Initial states:
    l = 5.2684 
    b = -0.0168 
    s = 1.3623 -0.2869 -0.3252 -0.7501

  sigma:  0.3874

     AIC     AICc      BIC 
154.2344 157.5677 173.6643 

Error measures:
                     ME      RMSE       MAE       MPE     MAPE      MASE       ACF1
Training set 0.01813475 0.3623624 0.2708647 0.3072365 3.143009 0.4639418 0.02346945

Forecasts:
# Verifica dei residui
checkresiduals(fit_hw)

    Ljung-Box test

data:  Residuals from Holt-Winters' additive method
Q* = 11.658, df = 8, p-value = 0.1671

Model df: 0.   Total lags used: 8

# Visualizzazione del modello
plot_model(fit_hw, revenue.ts)


plot_model_forecast(fit_hw, revenue.ts, forecast_horizon = 8)

# Modello di regressione lineare con componente quadratica
fit_lm_quad <- tslm(revenue.ts ~ trend + I(trend^2) + season)
summary(fit_lm_quad)

Call:
tslm(formula = revenue.ts ~ trend + I(trend^2) + season)

Residuals:
    Min      1Q  Median      3Q     Max 
-1.5486 -0.5636 -0.3143  0.6170  1.7710 

Coefficients:
              Estimate Std. Error t value Pr(>|t|)    
(Intercept)  4.8565249  0.3699855  13.126  < 2e-16 ***
trend        0.1579417  0.0231887   6.811 6.08e-09 ***
I(trend^2)  -0.0011992  0.0003457  -3.469 0.000992 ***
season2      0.5613607  0.2984077   1.881 0.064969 .  
season3      0.5819949  0.2985721   1.949 0.056106 .  
season4      2.1619026  0.2988452   7.234 1.18e-09 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 0.8439 on 58 degrees of freedom
Multiple R-squared:  0.8275,    Adjusted R-squared:  0.8126 
F-statistic: 55.65 on 5 and 58 DF,  p-value: < 2.2e-16
# Verifica dei residui
checkresiduals(fit_lm_quad)

    Breusch-Godfrey test for serial correlation of order up to 9

data:  Residuals from Linear regression model
LM test = 53.8, df = 9, p-value = 2.06e-08

# Visualizzazione del modello
plot_model(fit_lm_quad, revenue.ts)


plot_model_forecast(fit_lm_quad, revenue.ts, forecast_horizon = 8)

# Modello GAM con specifica dei nodi
fit_gam <- gam(revenue ~ s(time, k = 10) + s(quarter, bs = "cc", k = 4), data = revenue_gam_df)
summary(fit_gam)

Family: gaussian 
Link function: identity 

Formula:
revenue ~ s(time, k = 10) + s(quarter, bs = "cc", k = 4)

Parametric coefficients:
            Estimate Std. Error t value Pr(>|t|)    
(Intercept)   9.1400     0.1087   84.11   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Approximate significance of smooth terms:
             edf Ref.df      F p-value    
s(time)    6.485  7.626 33.139  <2e-16 ***
s(quarter) 1.127  2.000  1.646  0.0625 .  
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

R-sq.(adj) =  0.801   Deviance explained = 82.5%
GCV = 0.87314  Scale est. = 0.75565   n = 64
# Verifica dei residui
residuals_gam <- residuals(fit_gam)
plot(residuals_gam, ylab = "residuals")

dwtest(residuals_gam ~ revenue_gam_df$time)

    Durbin-Watson test

data:  residuals_gam ~ revenue_gam_df$time
DW = 2.5751, p-value = 0.9871
alternative hypothesis: true autocorrelation is greater than 0
# Visualizzazione del modello
plot(revenue.ts, ylab = "Billion", xlab = "Time")
lines(fitted(fit_gam), col = 2)

NA
NA
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKYGBge3J9CmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShkcGx5cikKbGlicmFyeShjb3JycGxvdCkKbGlicmFyeShyZWFkeGwpCmxpYnJhcnkobG10ZXN0KSAKbGlicmFyeShmb3JlY2FzdCkKbGlicmFyeShESU1PUkEpCmxpYnJhcnkoZnBwMikKbGlicmFyeSh0aWR5cikKbGlicmFyeShsdWJyaWRhdGUpCmBgYAoKYGBge3J9Cm51bWJlcl9vZl9lbXBsb3llZXMgPC0gcmVhZF9leGNlbCgifi9EZXNrdG9wL1VuaXBkL0dpdEh1Yi9CdXNpbmVzcy1Qcm9qZWN0L0J1c2luZXNzIFByb2plY3QvbnVtYmVyLW9mLWVtcGxveWVlcy54bHN4IikKcXVhcnRlcmx5X25ldF9pbmNvbWUgPC0gcmVhZF9leGNlbCgifi9EZXNrdG9wL1VuaXBkL0dpdEh1Yi9CdXNpbmVzcy1Qcm9qZWN0L0J1c2luZXNzIFByb2plY3QvcXVhcnRlcmx5LW5ldC1pbmNvbWUueGxzeCIpCnJlc2VhcmNoX2RldmVsb3BtZW50X3NwZW5kaW5nIDwtIHJlYWRfZXhjZWwoIn4vRGVza3RvcC9VbmlwZC9HaXRIdWIvQnVzaW5lc3MtUHJvamVjdC9CdXNpbmVzcyBQcm9qZWN0L3Jlc2VhcmNoLWRldmVsb3BtZW50LXNwZW5kaW5nLnhsc3giKQpyZXZlbnVlX2J5X3F1YXJ0ZXIgPC0gcmVhZF9leGNlbCgifi9EZXNrdG9wL1VuaXBkL0dpdEh1Yi9CdXNpbmVzcy1Qcm9qZWN0L0J1c2luZXNzIFByb2plY3QvcmV2ZW51ZS1ieS1xdWFydGVyLnhsc3giKQpyZXZlbnVlX2J5X3NlZ21lbnQgPC0gcmVhZF9leGNlbCgifi9EZXNrdG9wL1VuaXBkL0dpdEh1Yi9CdXNpbmVzcy1Qcm9qZWN0L0J1c2luZXNzIFByb2plY3QvcmV2ZW51ZS1ieS1zZWdtZW50Lnhsc3giKQpgYGAKCmBgYHtyfQojIFJpbXVvdmVyZSBsZSBwcmltZSA0IHJpZ2hlIGUgbCd1bHRpbWEgcmlnYQpyZXZlbnVlX2J5X3F1YXJ0ZXIgPC0gcmV2ZW51ZV9ieV9xdWFydGVyICU+JQogIHNsaWNlKDU6KG4oKSAtIDEpKQoKcmVzZWFyY2hfZGV2ZWxvcG1lbnRfc3BlbmRpbmcgPC0gcmVzZWFyY2hfZGV2ZWxvcG1lbnRfc3BlbmRpbmcgJT4lCiAgc2xpY2UoNDpuKCkpCgpudW1iZXJfb2ZfZW1wbG95ZWVzIDwtIG51bWJlcl9vZl9lbXBsb3llZXMgJT4lCiAgc2xpY2UoMjpuKCkpCmBgYAoKCmBgYHtyfQojIE5vcm1hbGl6emFyZSBpIGRhdGkKbm9ybWFsaXplIDwtIGZ1bmN0aW9uKHgpIHsKICByZXR1cm4oKHggLSBtZWFuKHgpKSAvIHNkKHgpKQp9CgojIFJpcGV0ZXJlIGkgdmFsb3JpIGFubnVhbGkgcGVyIGNpYXNjdW5vIGRlaSBxdWF0dHJvIHRyaW1lc3RyaQpyZXBlYXRfYW5udWFsX2RhdGEgPC0gZnVuY3Rpb24oYW5udWFsX2RhdGEpIHsKICByZXR1cm4ocmVwKGFubnVhbF9kYXRhLCBlYWNoID0gNCkpCn0KCmVtcGxveWVlc19yZXBlYXRlZCA8LSByZXBlYXRfYW5udWFsX2RhdGEobnVtYmVyX29mX2VtcGxveWVlcyRlbXBsb3llZXMpCnNwZW5kaW5nX3JlcGVhdGVkIDwtIHJlcGVhdF9hbm51YWxfZGF0YShyZXNlYXJjaF9kZXZlbG9wbWVudF9zcGVuZGluZyRiaWxsaW9uKQoKIyBOb3JtYWxpenphcmUgaSBkYXRpIGFubnVhbGkgcmlwZXR1dGkKbl9lbXBsb3llZXMgPC0gbm9ybWFsaXplKGVtcGxveWVlc19yZXBlYXRlZCkKbl9zcGVuZGluZyA8LSBub3JtYWxpemUoc3BlbmRpbmdfcmVwZWF0ZWQpCgpuX3JldmVudWUgPC0gbm9ybWFsaXplKHJldmVudWUpCm5fbmV0X2luY29tZSA8LSBub3JtYWxpemUobmV0X2luY29tZSkKCiMgQ3JlYXJlIHVuIGRhdGFmcmFtZSBjb21iaW5hdG8KY29tYmluZWRfZGF0YSA8LSBkYXRhLmZyYW1lKAogIFF1YXJ0ZXIgPSB0dCwKICBSZXZlbnVlID0gbl9yZXZlbnVlLAogIE5ldF9JbmNvbWUgPSBuX25ldF9pbmNvbWUsCiAgRW1wbG95ZWVzID0gbl9lbXBsb3llZXMsCiAgU3BlbmRpbmcgPSBuX3NwZW5kaW5nCikKCiMgVHJhc2Zvcm1hcmUgaWwgZGF0YWZyYW1lIGluIGZvcm1hdG8gbHVuZ28KY29tYmluZWRfZGF0YV9sb25nIDwtIGNvbWJpbmVkX2RhdGEgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjKCJSZXZlbnVlIiwgIk5ldF9JbmNvbWUiLCAiRW1wbG95ZWVzIiwgIlNwZW5kaW5nIiksIG5hbWVzX3RvID0gIk1ldHJpYyIsIHZhbHVlc190byA9ICJWYWx1ZSIpCgojIENyZWFyZSBpbCBncmFmaWNvCmdncGxvdChkYXRhID0gY29tYmluZWRfZGF0YV9sb25nLCBhZXMoeCA9IFF1YXJ0ZXIsIHkgPSBWYWx1ZSwgY29sb3IgPSBNZXRyaWMpKSArCiAgZ2VvbV9saW5lKCkgKwogIGxhYnMoeCA9ICJRdWFydGVyIiwgeSA9ICJWYWx1ZSIsIHRpdGxlID0gIlF1YXJ0ZXJseSBSZXZlbnVlIGFuZCBOZXQgSW5jb21lIikgKwogIHRoZW1lX21pbmltYWwoKQoKYGBgCgpgYGB7cn0KIyBTb3N0aXR1aXNjaSBpIHZhbG9yaSBOQSBjb24gemVybwpyZXZlbnVlX2J5X3NlZ21lbnRbaXMubmEocmV2ZW51ZV9ieV9zZWdtZW50KV0gPC0gMAoKIyBUcmFzZm9ybWEgaSBkYXRpIGluIGZvcm1hdG8gbHVuZ28gcGVyIGdncGxvdDIKZGZfbG9uZyA8LSByZXZlbnVlX2J5X3NlZ21lbnQgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSAteWVhciwgbmFtZXNfdG8gPSAiY2F0ZWdvcnkiLCB2YWx1ZXNfdG8gPSAidmFsdWUiKQoKIyBTZWxlemlvbmEgdW5hIHBhbGV0dGUgZGkgY29sb3JpIGNvbiBhYmJhc3RhbnphIHZhcmlhemlvbmkKcGFsZXR0ZV9jb2xvcnMgPC0gYygiIzY2YzJhNSIsICIjZmM4ZDYyIiwgIiM4ZGEwY2IiLCAiI2U3OGFjMyIsICIjYTZkODU0IiwgCiAgICAgICAgICAgICAgICAgICAgIiNmZmQ5MmYiLCAiI2U1YzQ5NCIsICIjYjNiM2IzIiwgIiMxYjllNzciLCAiI2Q5NWYwMiIsIAogICAgICAgICAgICAgICAgICAgICIjNzU3MGIzIiwgIiNlNzI5OGEiLCAiIzY2YTYxZSIsICIjZTZhYjAyIiwgIiNhNjc2MWQiLCAiIzY2NjY2NiIpCgojIENyZWEgaWwgZ3JhZmljbwpnZ3Bsb3QoZGZfbG9uZywgYWVzKHggPSBmYWN0b3IoeWVhciksIHkgPSB2YWx1ZSwgZmlsbCA9IGNhdGVnb3J5KSkgKwogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJzdGFjayIpICsgICMgVXNhICJzdGFjayIgcGVyIGltcGlsYXJlIGxlIGJhcnJlCiAgbGFicyh4ID0gIlllYXIiLCB5ID0gIlZhbHVlIiwgdGl0bGUgPSAiQW5udWFsIERhdGEgYnkgQ2F0ZWdvcnkiKSArCiAgdGhlbWVfbWluaW1hbCgpICsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLCAKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAicmlnaHQiLCAgIyBTcG9zdGEgbGEgbGVnZW5kYSBhIGRlc3RyYQogICAgICAgIGxlZ2VuZC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA3KSwKICAgICAgICBsZWdlbmQudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKSArCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gcGFsZXR0ZV9jb2xvcnMpICsKICBndWlkZXMoZmlsbCA9IGd1aWRlX2xlZ2VuZChuY29sID0gMSwgYnlyb3cgPSBUUlVFKSkgICMgTWlnbGlvcmEgbGEgbGVnZ2liaWxpdMOgIGRlbGxhIGxlZ2VuZGEKCmBgYAoKYGBge3J9CiMgQXNzaWN1cmF0aSBjaGUgdHV0dGUgbGUgY29sb25uZSB1dGlsaXp6YXRlIHBlciBsYSBjb3JyZWxhemlvbmUgc2lhbm8gbnVtZXJpY2hlCiMgU3VwcG9uaWFtbyBjaGUgaSBkYXRpIHNpYW5vIG5lbGxlIGNvbG9ubmUgMiBkZWxsZSByaXNwZXR0aXZlIHRhYmVsbGUgKGFkYXR0YSBsJ2luZGljZSBkaSBjb2xvbm5hIHNlIG5lY2Vzc2FyaW8pCmRhdGFfY29tYmluZWQgPC0gZGF0YS5mcmFtZSgKICByZXZlbnVlID0gcmV2ZW51ZV9ieV9xdWFydGVyJGJpbGxpb24sCiAgbmV0X2luY29tZSA9IHF1YXJ0ZXJseV9uZXRfaW5jb21lJGluY29tZSwKICBlbXBsb3llZXMgPSBlbXBsb3llZXNfcmVwZWF0ZWQsCiAgcm5kX3NwZW5kaW5nID0gc3BlbmRpbmdfcmVwZWF0ZWQKKQoKIyBDYWxjb2xvIGRlbGxhIG1hdHJpY2UgZGkgY29ycmVsYXppb25lCmNvcnJlbGF0aW9uX21hdHJpeCA8LSBjb3IoZGF0YV9jb21iaW5lZCwgdXNlID0gImNvbXBsZXRlLm9icyIpCgojIFZpc3VhbGl6emF6aW9uZSBkZWxsYSBtYXRyaWNlIGRpIGNvcnJlbGF6aW9uZQpwcmludChjb3JyZWxhdGlvbl9tYXRyaXgpCgojIFNlIGRlc2lkZXJpIHVuYSB2aXN1YWxpenphemlvbmUgZ3JhZmljYQpsaWJyYXJ5KGNvcnJwbG90KQpjb3JycGxvdChjb3JyZWxhdGlvbl9tYXRyaXgsIG1ldGhvZCA9ICJjaXJjbGUiKQoKIyBDcmVhemlvbmUgZGVsbGUgc2VyaWUgdGVtcG9yYWxpCnJldmVudWUudHMgPC0gdHMocmV2ZW51ZV9ieV9xdWFydGVyJGJpbGxpb24sIGZyZXF1ZW5jeSA9IDQpCm5ldF9pbmNvbWUudHMgPC0gdHMocXVhcnRlcmx5X25ldF9pbmNvbWUkaW5jb21lLCBmcmVxdWVuY3kgPSA0KQplbXBsb3llZXNfcmVwZWF0ZWQgPC0gdHMoZW1wbG95ZWVzX3JlcGVhdGVkLCBmcmVxdWVuY3kgPSA0KQpzcGVuZGluZ19yZXBlYXRlZCA8LSB0cyhzcGVuZGluZ19yZXBlYXRlZCwgZnJlcXVlbmN5ID0gNCkKCiMgRGlmZmVyZW56aWF6aW9uZSBkZWxsZSBzZXJpZSB0ZW1wb3JhbGkKZGlmZl9yZXZlbnVlIDwtIGRpZmYocmV2ZW51ZS50cykKZGlmZl9uZXRfaW5jb21lIDwtIGRpZmYobmV0X2luY29tZS50cykKZGlmZl9lbXBsb3llZXMgPC0gZGlmZihlbXBsb3llZXNfcmVwZWF0ZWQpCmRpZmZfc3BlbmRpbmcgPC0gZGlmZihzcGVuZGluZ19yZXBlYXRlZCkKCiMgQ3JlYXppb25lIGRlbCBkYXRhZnJhbWUgY29uIGxlIHNlcmllIGRpZmZlcmVuemlhdGUKZGF0YV9jb21iaW5lZF9kaWZmIDwtIGRhdGEuZnJhbWUoCiAgZGlmZl9yZXZlbnVlID0gYXMubnVtZXJpYyhkaWZmX3JldmVudWUpLAogIGRpZmZfbmV0X2luY29tZSA9IGFzLm51bWVyaWMoZGlmZl9uZXRfaW5jb21lKSwKICBkaWZmX2VtcGxveWVlcyA9IGFzLm51bWVyaWMoZGlmZl9lbXBsb3llZXMpLAogIGRpZmZfc3BlbmRpbmcgPSBhcy5udW1lcmljKGRpZmZfc3BlbmRpbmcpCikKCiMgQ2FsY29sbyBkZWxsYSBtYXRyaWNlIGRpIGNvcnJlbGF6aW9uZQpjb3JyZWxhdGlvbl9tYXRyaXhfZGlmZiA8LSBjb3IoZGF0YV9jb21iaW5lZF9kaWZmLCB1c2UgPSAiY29tcGxldGUub2JzIikKCiMgVmlzdWFsaXp6YXppb25lIGRlbGxhIG1hdHJpY2UgZGkgY29ycmVsYXppb25lCnByaW50KGNvcnJlbGF0aW9uX21hdHJpeF9kaWZmKQoKIyBWaXN1YWxpenphemlvbmUgZ3JhZmljYSBkZWxsYSBtYXRyaWNlIGRpIGNvcnJlbGF6aW9uZQpjb3JycGxvdChjb3JyZWxhdGlvbl9tYXRyaXhfZGlmZiwgbWV0aG9kID0gImNpcmNsZSIpCgpgYGAKCgpgYGB7cn0KdHQgPC0gMTpOUk9XKHJldmVudWVfYnlfcXVhcnRlcikKcmV2ZW51ZSA8LSByZXZlbnVlX2J5X3F1YXJ0ZXIkYmlsbGlvbgpuZXRfaW5jb21lIDwtIHF1YXJ0ZXJseV9uZXRfaW5jb21lJGluY29tZQpyZXZlbnVlX2J5X3F1YXJ0ZXIkcXVhcnRlciA8LSBhcy55ZWFycXRyKHJldmVudWVfYnlfcXVhcnRlciRxdWFydGVyLCBmb3JtYXQgPSAiUSVxICcleSIpCgp0c2Rpc3BsYXkocmV2ZW51ZSkKCiMgQ2FsY29sbyBkZWxsYSBtZWRpYSBtb2JpbGUgKGVzZW1waW8gY29uIGZpbmVzdHJhIGRpIDEyIG1lc2kgcGVyIGRhdGkgbWVuc2lsaSkKbW92aW5nX2F2ZXJhZ2UgPC0gbWEocmV2ZW51ZSwgb3JkZXIgPSAxMikKCmdncGxvdChkYXRhID0gcmV2ZW51ZV9ieV9xdWFydGVyLCBhZXMoeCA9IHR0KSkgKwogIGdlb21fbGluZShhZXMoeSA9IGJpbGxpb24pKSArCiAgZ2VvbV9saW5lKGFlcyh5ID0gbW92aW5nX2F2ZXJhZ2UpLCBjb2xvciA9ICJyZWQiKSArCiAgbGFicyh4ID0gIlF1YXJ0ZXIiLCB5ID0gIkJpbGxpb24iLCB0aXRsZSA9ICJRdWFydGVyIHZzLiBCaWxsaW9uIikKCgoKYGBgCmBgYHtyfQojIEFnZ2l1bmdpIGNvbG9ubmUgcGVyIGFubm8gZSB0cmltZXN0cmUKcmV2ZW51ZV9ieV9xdWFydGVyIDwtIHJldmVudWVfYnlfcXVhcnRlciAlPiUKICBtdXRhdGUoCiAgICB5ZWFyID0gYXMuaW50ZWdlcihmb3JtYXQocXVhcnRlciwgIiVZIikpLAogICAgcXVhcnRlcl9udW0gPSBhcy5pbnRlZ2VyKGZvcm1hdChxdWFydGVyLCAiJXEiKSkKICApCgojIENyZWEgdW4gZ3JhZmljbyBzdGFnaW9uYWxlCmdncGxvdChyZXZlbnVlX2J5X3F1YXJ0ZXIsIGFlcyh4ID0gcXVhcnRlcl9udW0sIHkgPSBiaWxsaW9uLCBncm91cCA9IHllYXIsIGNvbG9yID0gZmFjdG9yKHllYXIpKSkgKwogIGdlb21fbGluZSgpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gMTo0LCBsYWJlbHMgPSBjKCJRMSIsICJRMiIsICJRMyIsICJRNCIpKSArCiAgbGFicyh4ID0gIlF1YXJ0ZXIiLCB5ID0gIlJldmVudWUgKEJpbGxpb24pIiwgdGl0bGUgPSAiU2Vhc29uYWwgUGxvdDogUmV2ZW51ZSBieSBRdWFydGVyIiwgY29sb3IgPSAiWWVhciIpICsKICB0aGVtZV9taW5pbWFsKCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJyaWdodCIpCmBgYAoKCgpgYGB7cn0KI0RhdG8gY2hlIGkgZGF0aSBtb3N0cmFubyB1bmEgdGVuZGVuemEsIHBvdHJlYmJlIGVzc2VyZSBuZWNlc3NhcmlvIGRpZmZlcmVuemlhcmUgaSBkYXRpIHBlciByZW5kZXJsaSBzdGF6aW9uYXJpIHByaW1hIGRpIGFwcGxpY2FyZSB1biBtb2RlbGxvIEFSSU1BLgoKI0xhIGRpZmZlcmVuemlhemlvbmUgw6ggdW5hIHRlY25pY2EgdXRpbGl6emF0YSBuZWxsJ2FuYWxpc2kgZGVsbGUgc2VyaWUgdGVtcG9yYWxpIHBlciB0cmFzZm9ybWFyZSB1bmEgc2VyaWUgbm9uIHN0YXppb25hcmlhIGluIHVuYSBzdGF6aW9uYXJpYS4gVW5hIHNlcmllIHRlbXBvcmFsZSDDqCBzdGF6aW9uYXJpYSBxdWFuZG8gbGUgc3VlIHByb3ByaWV0w6Agc3RhdGlzdGljaGUsIGNvbWUgbGEgbWVkaWEgZSBsYSB2YXJpYW56YSwgbm9uIGNhbWJpYW5vIG5lbCB0ZW1wby4gTGEgc3RhemlvbmFyaWV0w6Agw6ggdW4gcmVxdWlzaXRvIGZvbmRhbWVudGFsZSBwZXIgbCdhcHBsaWNhemlvbmUgZGkgbW9sdGkgbW9kZWxsaSBkaSBzZXJpZSB0ZW1wb3JhbGksIGNvbWUgbCdBUklNQSwgaW4gcXVhbnRvIHBlcm1ldHRlIGRpIGFzc3VtZXJlIGNoZSBpIHByb2Nlc3NpIGdlbmVyYXRpIGRhaSBkYXRpIHNpYW5vIGludmFyaWFudGkgbmVsIHRlbXBvLgoKIyBEaWZmZXJlbnppYXppb25lIGRlaSBkYXRpCmRpZmZfcmV2ZW51ZSA8LSBkaWZmKHJldmVudWUpCgojIFZpc3VhbGl6emF6aW9uZSBkZWkgZGF0aSBkaWZmZXJlbnppYXRpCnBsb3QoZGlmZl9yZXZlbnVlLCB0eXBlID0gImwiLCBtYWluID0gIkRpZmZlcmVuY2VkIFJldmVudWUiKQoKIyBUZXN0IGRpIHN0YXppb25hcmlldMOgIChhZCBlc2VtcGlvLCB0ZXN0IGRpIERpY2tleS1GdWxsZXIgYXVtZW50YXRvKQpsaWJyYXJ5KHRzZXJpZXMpCmFkZi50ZXN0KGRpZmZfcmV2ZW51ZSkKCgpgYGAKCgoKYGBge3J9CiMgQ3JlYXJlIGxhIHNlcmllIHRlbXBvcmFsZQpyZXZlbnVlX3RzIDwtIHRzKHJldmVudWVfYnlfcXVhcnRlciRiaWxsaW9uLCBzdGFydD1jKDIwMDcsIDEpLCBmcmVxdWVuY3k9NCkKCiMgRGVjb21wb3JyZSBsYSBzZXJpZSB0ZW1wb3JhbGUKZGVjb21wb3NlZF9yZXZlbnVlIDwtIHN0bChyZXZlbnVlX3RzLCBzLndpbmRvdz0icGVyaW9kaWMiKQoKIyBWaXN1YWxpenphcmUgbGEgZGVjb21wb3NpemlvbmUKYXV0b3Bsb3QoZGVjb21wb3NlZF9yZXZlbnVlKSArCiAgbGFicyh0aXRsZSA9ICJEZWNvbXBvc2l0aW9uIG9mIFF1YXJ0ZXJseSBSZXZlbnVlIiwgeCA9ICJUaW1lIikKCiMgRXN0cmFycmUgbGEgY29tcG9uZW50ZSBzdGFnaW9uYWxlCnNlYXNvbmFsX2NvbXBvbmVudCA8LSBkZWNvbXBvc2VkX3JldmVudWUkdGltZS5zZXJpZXNbLCAic2Vhc29uYWwiXQoKIyBDcmVhcmUgaWwgZ3JhZmljbyBkZWxsYSBzdGFnaW9uYWxpdMOgCmdncGxvdChkYXRhID0gZGF0YS5mcmFtZShRdWFydGVyID0gdGltZShyZXZlbnVlX3RzKSwgU2Vhc29uYWwgPSBzZWFzb25hbF9jb21wb25lbnQpLCAKICAgICAgIGFlcyh4ID0gUXVhcnRlciwgeSA9IFNlYXNvbmFsKSkgKwogIGdlb21fbGluZShjb2xvciA9ICJibHVlIikgKwogIGxhYnMoeCA9ICJRdWFydGVyIiwgeSA9ICJTZWFzb25hbCBDb21wb25lbnQiLCB0aXRsZSA9ICJTZWFzb25hbCBDb21wb25lbnQgb2YgUXVhcnRlcmx5IFJldmVudWUiKSArCiAgdGhlbWVfbWluaW1hbCgpCgpgYGAKCgpgYGB7cn0KbGlicmFyeShmb3JlY2FzdCkKbGlicmFyeSh0c2VyaWVzKQoKIyBDcmVhcmUgbGEgc2VyaWUgdGVtcG9yYWxlCnJldmVudWVfdHMgPC0gdHMocmV2ZW51ZV9ieV9xdWFydGVyJGJpbGxpb24sIHN0YXJ0PWMoMjAwNywgMSksIGZyZXF1ZW5jeT00KQoKIyBEaWZmZXJlbnppYXJlIGkgZGF0aSBwZXIgcmVuZGVybGkgc3RhemlvbmFyaQpkaWZmX3JldmVudWUgPC0gZGlmZihyZXZlbnVlX3RzLCBkaWZmZXJlbmNlcz0xKQoKIyBDYWxjb2xhcmUgZSB0cmFjY2lhcmUgbCdBQ0YgZSBsYSBQQUNGIGRlbGxhIHNlcmllIGRpZmZlcmVuemlhdGEKYWNmKGRpZmZfcmV2ZW51ZSwgbWFpbj0iQUNGIG9mIERpZmZlcmVuY2VkIFJldmVudWUiKQpwYWNmKGRpZmZfcmV2ZW51ZSwgbWFpbj0iUEFDRiBvZiBEaWZmZXJlbmNlZCBSZXZlbnVlIikKCiMgVXRpbGl6emFyZSBhdXRvLmFyaW1hIHBlciB0cm92YXJlIGlsIG1pZ2xpb3IgbW9kZWxsbyBBUklNQQpiZXN0X2FyaW1hX21vZGVsIDwtIGF1dG8uYXJpbWEocmV2ZW51ZV90cykKc3VtbWFyeShiZXN0X2FyaW1hX21vZGVsKQoKcmVzaWR1YWxzX2FyaW1hIDwtIHJlc2lkdWFscyhiZXN0X2FyaW1hX21vZGVsKQoKIyBWaXN1YWxpenphcmUgaSByZXNpZHVpIGRlbCBtb2RlbGxvCmNoZWNrcmVzaWR1YWxzKGJlc3RfYXJpbWFfbW9kZWwpCgojIFByZXZlZGVyZSBpIHByb3NzaW1pIDggdHJpbWVzdHJpCmZvcmVjYXN0X2hvcml6b24gPC0gMTIKZm9yZWNhc3RfcmV2ZW51ZSA8LSBmb3JlY2FzdChiZXN0X2FyaW1hX21vZGVsLCBoID0gZm9yZWNhc3RfaG9yaXpvbikKCiMgVmlzdWFsaXp6YXJlIGxlIHByZXZpc2lvbmkKYXV0b3Bsb3QoZm9yZWNhc3RfcmV2ZW51ZSkgKwogIGxhYnModGl0bGUgPSAiUmV2ZW51ZSBGb3JlY2FzdCB3aXRoIEFSSU1BIiwgeCA9ICJEYXRlIiwgeSA9ICJSZXZlbnVlIChCaWxsaW9uKSIpICsKICBhdXRvbGF5ZXIoZml0dGVkKGJlc3RfYXJpbWFfbW9kZWwpLCBzZXJpZXMgPSAiRml0dGVkIiwgUEkgPSBGQUxTRSkKCmBgYApgYGB7cn0KYWlyLm1vZGVsIDwtIEFyaW1hKHdpbmRvdyhyZXZlbnVlX3RzLGVuZD0yMDIyKSxvcmRlcj1jKDIsMCwyKSwKICAgICAgICAgICAgICAgICAgIHNlYXNvbmFsPWxpc3Qob3JkZXI9YygwLDEsMCkscGVyaW9kPTQpLGxhbWJkYT0wKQpwbG90KGZvcmVjYXN0KGFpci5tb2RlbCxoPTEyKSkKbGluZXMocmV2ZW51ZV90cykKYGBgCgoKCmBgYHtyfQojIEZ1bnppb25lIHBlciB2aXN1YWxpenphcmUgaWwgbW9kZWxsbwpwbG90X21vZGVsIDwtIGZ1bmN0aW9uKG1vZGVsLCBkYXRhKSB7CiAgcGxvdChkYXRhLCB5bGFiPSJCaWxsaW9uIiwgeGxhYj0iVGltZSIpCiAgbGluZXMoZml0dGVkKG1vZGVsKSwgY29sPTIpCn0KCnBsb3RfbW9kZWxfZm9yZWNhc3QgPC0gZnVuY3Rpb24obW9kZWwsIGRhdGEsIGZvcmVjYXN0X2hvcml6b24pIHsKICBmb3JlY2FzdGVkX3ZhbHVlcyA8LSBmb3JlY2FzdChtb2RlbCwgaCA9IGZvcmVjYXN0X2hvcml6b24pCiAgcGxvdChmb3JlY2FzdGVkX3ZhbHVlcywgeWxhYiA9ICJCaWxsaW9uIiwgeGxhYiA9ICJUaW1lIikKICBsaW5lcyhmaXR0ZWQobW9kZWwpLCBjb2wgPSAyKQp9CgojIE1vZGVsbG8gY29uIHRyZW5kIGUgc3RhZ2lvbmFsaXTDoApmaXRfbG0gPC0gdHNsbShyZXZlbnVlLnRzIH4gdHJlbmQgKyBzZWFzb24pCnN1bW1hcnkoZml0X2xtKQoKIyBWZXJpZmljYSBkZWkgcmVzaWR1aQpjaGVja3Jlc2lkdWFscyhmaXRfbG0pCgojIFZpc3VhbGl6emF6aW9uZSBkZWwgbW9kZWxsbwpwbG90X21vZGVsKGZpdF9sbSwgcmV2ZW51ZS50cykKCnBsb3RfbW9kZWxfZm9yZWNhc3QoZml0X2xtLCByZXZlbnVlLnRzLCBmb3JlY2FzdF9ob3Jpem9uID0gOCkKCmBgYAoKCmBgYHtyfQojIE1vZGVsbG8gSG9sdC1XaW50ZXJzCmZpdF9odyA8LSBodyhyZXZlbnVlLnRzLCBzZWFzb25hbCA9ICJhZGRpdGl2ZSIpCnN1bW1hcnkoZml0X2h3KQoKIyBWZXJpZmljYSBkZWkgcmVzaWR1aQpjaGVja3Jlc2lkdWFscyhmaXRfaHcpCgojIFZpc3VhbGl6emF6aW9uZSBkZWwgbW9kZWxsbwpwbG90X21vZGVsKGZpdF9odywgcmV2ZW51ZS50cykKCnBsb3RfbW9kZWxfZm9yZWNhc3QoZml0X2h3LCByZXZlbnVlLnRzLCBmb3JlY2FzdF9ob3Jpem9uID0gOCkKCmBgYApgYGB7cn0KIyBNb2RlbGxvIGRpIHJlZ3Jlc3Npb25lIGxpbmVhcmUgY29uIGNvbXBvbmVudGUgcXVhZHJhdGljYQpmaXRfbG1fcXVhZCA8LSB0c2xtKHJldmVudWUudHMgfiB0cmVuZCArIEkodHJlbmReMikgKyBzZWFzb24pCnN1bW1hcnkoZml0X2xtX3F1YWQpCgojIFZlcmlmaWNhIGRlaSByZXNpZHVpCmNoZWNrcmVzaWR1YWxzKGZpdF9sbV9xdWFkKQoKIyBWaXN1YWxpenphemlvbmUgZGVsIG1vZGVsbG8KcGxvdF9tb2RlbChmaXRfbG1fcXVhZCwgcmV2ZW51ZS50cykKCnBsb3RfbW9kZWxfZm9yZWNhc3QoZml0X2xtX3F1YWQsIHJldmVudWUudHMsIGZvcmVjYXN0X2hvcml6b24gPSA4KQoKYGBgCmBgYHtyfQojIE1vZGVsbG8gR0FNIGNvbiBzcGVjaWZpY2EgZGVpIG5vZGkKZml0X2dhbSA8LSBnYW0ocmV2ZW51ZSB+IHModGltZSwgayA9IDEwKSArIHMocXVhcnRlciwgYnMgPSAiY2MiLCBrID0gNCksIGRhdGEgPSByZXZlbnVlX2dhbV9kZikKc3VtbWFyeShmaXRfZ2FtKQoKIyBWZXJpZmljYSBkZWkgcmVzaWR1aQpyZXNpZHVhbHNfZ2FtIDwtIHJlc2lkdWFscyhmaXRfZ2FtKQpwbG90KHJlc2lkdWFsc19nYW0sIHlsYWIgPSAicmVzaWR1YWxzIikKZHd0ZXN0KHJlc2lkdWFsc19nYW0gfiByZXZlbnVlX2dhbV9kZiR0aW1lKQoKIyBWaXN1YWxpenphemlvbmUgZGVsIG1vZGVsbG8KcGxvdChyZXZlbnVlLnRzLCB5bGFiID0gIkJpbGxpb24iLCB4bGFiID0gIlRpbWUiKQpsaW5lcyhmaXR0ZWQoZml0X2dhbSksIGNvbCA9IDIpCgoKYGBgCgo=